package com.huiyeji.dynamic.core.bean;

import com.huiyeji.dynamic.core.DynamicContext;
import com.huiyeji.dynamic.core.DynamicStatement;
import com.huiyeji.dynamic.core.DynamicStatementPointer;
import com.huiyeji.dynamic.core.annotations.*;

import java.util.ArrayList;
import java.util.List;

/**
 * @author Huiyeji
 */
@DynamicBean("condition")
public class DynamicCondition {

    private boolean condition;

    private boolean fix = false;

    private final String conditionObjectName;

    private final DynamicContext context;

    private final DynamicStatementPointer pointer;

    private final int trueIndex;

    private final int falseIndex;

    private final int endIndex;

    public DynamicCondition(DynamicContext context){
        this(context,true);
    }

    public DynamicCondition(DynamicContext context,boolean condition){
        this.context = context;
        this.condition = condition;
        this.pointer = context.getPointer();
        List<DynamicStatement> statements = pointer.getStatements();
        int currentPosition = pointer.getCurrentPosition();
        DynamicStatement currentStatement = statements.get(currentPosition);
        conditionObjectName = currentStatement.getDynamicResultName();
        List<Integer> trueIndexList = new ArrayList<Integer>();
        List<Integer> falseIndexList = new ArrayList<Integer>();
        List<Integer> endIndexList = new ArrayList<Integer>();
        for (int i = currentPosition + 1; i < statements.size(); i++) {
            DynamicStatement statement = statements.get(i);
            if (conditionObjectName.equals(statement.getDynamicObjectName())){
                if ("true".equals(statement.getDynamicMethodName())){
                    trueIndexList.add(i);
                } else if ("false".equals(statement.getDynamicMethodName())){
                    falseIndexList.add(i);
                } else if ("end".equals(statement.getDynamicMethodName())){
                    endIndexList.add(i);
                    break;
                }
            }
        }

        if (trueIndexList.size() != 1 || falseIndexList.size() != 1 || endIndexList.size() != 1){
            throw new RuntimeException("condition statement error");
        }

        this.trueIndex = trueIndexList.get(0);
        this.falseIndex = falseIndexList.get(0);
        this.endIndex = endIndexList.get(0);

        if (!(this.endIndex > this.falseIndex && this.falseIndex > this.trueIndex)){
            throw new RuntimeException("condition statement sort error");
        }
    }

    @DynamicMethod
    public void and(boolean condition){
        this.condition = this.condition && condition;
    }

    @DynamicMethod
    public void or(boolean condition){
        this.condition = this.condition || condition;
    }

    @DynamicMethod("get")
    public boolean getCondition(){
        return condition;
    }

    @DynamicMethod("set")
    public void init(boolean condition){
        this.condition = condition;
        this.fix = true;
    }

    @DynamicMethod("true")
    public void _true(){
        if (!condition){
            pointer.setNextPosition(falseIndex);
        }
    }

    @DynamicMethod("false")
    public void _false(){
        if (condition){
            pointer.setNextPosition(endIndex);
        }
    }

    @DynamicMethod("end")
    public void _end(){
        if (!fix){
            context.removeObject(conditionObjectName);
            context.getFactory().removeDynamicObject(conditionObjectName);
        }
    }
}
